package cn.iocoder.yudao.module.system.service.examtest;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.controller.admin.examtest.vo.*;
import cn.iocoder.yudao.module.system.convert.examtest.ExamTestConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.examclass.ExamClassDO;
import cn.iocoder.yudao.module.system.dal.dataobject.examtest.ExamTestDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.examtest.ExamTestMapper;
import cn.iocoder.yudao.module.system.dal.mysql.examscore.ExamScoreMapper;
import cn.iocoder.yudao.module.system.service.examclass.ExamClassService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;

/**
 * 考试信息 Service 实现类
 *
 * @author 芋道源码
 */
@Service("examTestManagementServiceImpl")
@Validated
@Slf4j
public class ExamTestServiceImpl implements ExamTestService {

    @Resource
    private ExamTestMapper examTestMapper;
    
    @Resource
    private ExamScoreMapper examScoreMapper;
    
    @Resource
    private ExamClassService examClassService;
    
    @Resource
    private AdminUserService adminUserService;

    @Override
    public Long createExamTest(ExamTestCreateReqVO createReqVO) {
        // 校验班级存在
        for (Long classId : createReqVO.getClassIds()) {
            examClassService.getExamClass(classId);
        }
        
        // 插入
        ExamTestDO examTest = ExamTestConvert.INSTANCE.convert(createReqVO);
        if (examTest.getTotalScore() == null) {
            examTest.setTotalScore(new BigDecimal("750.00")); // 默认总分750
        }
        
        // 设置当前登录用户的部门ID（用于数据权限控制）
        Long currentUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();
        if (currentUserDeptId != null) {
            examTest.setDeptId(currentUserDeptId);
            log.debug("设置考试部门ID: {}, 考试: {}", currentUserDeptId, createReqVO.getExamName());
        } else {
            log.warn("当前登录用户未设置部门ID，考试将不设置部门信息: {}", createReqVO.getExamName());
        }
        
        examTestMapper.insert(examTest);
        
        // 返回
        return examTest.getId();
    }

    @Override
    public void updateExamTest(ExamTestUpdateReqVO updateReqVO) {
        // 校验存在
        ExamTestDO examTest = validateExamTestExists(updateReqVO.getId());
        
        // 校验状态是否允许修改
        if (examTest.getStatus() != null && examTest.getStatus() == 3) {
            throw exception(EXAM_TEST_MANAGE_STATUS_NOT_ALLOW_UPDATE);
        }
        
        // 更新
        ExamTestDO updateObj = ExamTestConvert.INSTANCE.convert(updateReqVO);
        examTestMapper.updateById(updateObj);
    }

    @Override
    public void deleteExamTest(Long id) {
        // 校验存在
        ExamTestDO examTest = validateExamTestExists(id);
        
        // 校验状态是否允许删除
        if (examTest.getStatus() != null && examTest.getStatus() != 1) {
            throw exception(EXAM_TEST_MANAGE_STATUS_NOT_ALLOW_DELETE);
        }
        
        // 校验是否有成绩记录
        Long scoreCount = examScoreMapper.selectCountByExamId(id);
        if (scoreCount > 0) {
            throw exception(EXAM_TEST_MANAGE_HAS_SCORES);
        }
        
        // 删除
        examTestMapper.deleteById(id);
    }

    private ExamTestDO validateExamTestExists(Long id) {
        ExamTestDO examTest = examTestMapper.selectById(id);
        if (examTest == null) {
            throw exception(EXAM_TEST_MANAGE_NOT_EXISTS);
        }
        return examTest;
    }

    @Override
    public ExamTestDO getExamTest(Long id) {
        return examTestMapper.selectById(id);
    }

    @Override
    public List<ExamTestDO> getExamTestList(Collection<Long> ids) {
        return examTestMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<ExamTestDO> getExamTestPage(ExamTestPageReqVO pageReqVO) {
        return examTestMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ExamTestDO> getExamTestList(ExamTestPageReqVO exportReqVO) {
        return examTestMapper.selectList(exportReqVO);
    }

    @Override
    public List<ExamTestDO> getExamTestListByClassId(Long classId) {
        return examTestMapper.selectListByClassId(classId);
    }



    @Override
    public List<ExamTestDO> getExamTestListByStatus(Integer status) {
        return examTestMapper.selectListByStatus(status);
    }

    @Override
    public void updateExamTestStatus(Long id, Integer status) {
        // 校验存在
        validateExamTestExists(id);
        
        // 更新状态
        ExamTestDO updateObj = new ExamTestDO();
        updateObj.setId(id);
        updateObj.setStatus(status);
        examTestMapper.updateById(updateObj);
    }

    @Override
    public void startExamTest(Long id) {
        // 校验存在
        ExamTestDO examTest = validateExamTestExists(id);
        
        // 校验状态
        if (examTest.getStatus() != null && examTest.getStatus() != 1) {
            throw exception(EXAM_TEST_MANAGE_STATUS_NOT_ALLOW_UPDATE);
        }
        
        // 更新状态为进行中
        updateExamTestStatus(id, 2);
    }

    @Override
    public void endExamTest(Long id) {
        // 校验存在
        ExamTestDO examTest = validateExamTestExists(id);
        
        // 校验状态
        if (examTest.getStatus() != null && examTest.getStatus() != 2) {
            throw exception(EXAM_TEST_MANAGE_STATUS_NOT_ALLOW_UPDATE);
        }
        
        // 更新状态为已结束
        updateExamTestStatus(id, 3);
    }

    @Override
    public ExamTestTreeRespVO getExamTestTree(Long id) {
        // 获取考试信息
        ExamTestDO examTest = getExamTest(id);
        if (examTest == null) {
            throw exception(EXAM_TEST_MANAGE_NOT_EXISTS);
        }
        
        return buildExamTestTree(examTest);
    }

    @Override
    public List<ExamTestTreeRespVO> getExamTestTreeList(ExamTestPageReqVO pageReqVO) {
        // 获取考试列表
        List<ExamTestDO> examTestList = examTestMapper.selectList(pageReqVO);
        if (CollUtil.isEmpty(examTestList)) {
            return Collections.emptyList();
        }
        
        // 构建树形结构列表
        return examTestList.stream()
                .map(this::buildExamTestTree)
                .collect(Collectors.toList());
    }

    /**
     * 构建考试信息树形结构
     *
     * @param examTest 考试信息
     * @return 树形结构
     */
    private ExamTestTreeRespVO buildExamTestTree(ExamTestDO examTest) {
        ExamTestTreeRespVO treeVO = ExamTestTreeRespVO.builder()
                .id(examTest.getId())
                .examName(examTest.getExamName())
                .examType(examTest.getExamType())
                .examDate(examTest.getExamDate())
                .totalScore(examTest.getTotalScore())
                .description(examTest.getDescription())
                .status(examTest.getStatus())
                .createTime(examTest.getCreateTime())
                .build();
        
        // 获取班级信息
        List<ExamTestTreeRespVO.ExamClassNode> classNodes = new ArrayList<>();
        if (CollUtil.isNotEmpty(examTest.getClassIds())) {
            // 批量获取班级信息
            List<ExamClassDO> classList = examClassService.getExamClassList(examTest.getClassIds());
            
            // 批量获取教师信息
            Set<Long> teacherIds = classList.stream()
                    .map(ExamClassDO::getTeacherId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            Map<Long, AdminUserDO> teacherMap = new HashMap<>();
            if (CollUtil.isNotEmpty(teacherIds)) {
                List<AdminUserDO> teachers = adminUserService.getUserList(teacherIds);
                teacherMap = teachers.stream()
                        .collect(Collectors.toMap(AdminUserDO::getId, teacher -> teacher));
            }
            
            // 构建班级节点
            for (ExamClassDO examClass : classList) {
                AdminUserDO teacher = teacherMap.get(examClass.getTeacherId());
                ExamTestTreeRespVO.ExamClassNode classNode = ExamTestTreeRespVO.ExamClassNode.builder()
                        .classId(examClass.getId())
                        .className(examClass.getClassName())
                        .classCode(examClass.getClassCode())
                        .grade(examClass.getGrade())
                        .studentCount(examClass.getStudentCount())
                        .teacherId(examClass.getTeacherId())
                        .teacherName(teacher != null ? teacher.getNickname() : null)
                        .status(examClass.getStatus())
                        .build();
                classNodes.add(classNode);
            }
        }
        
        treeVO.setClassList(classNodes);
        return treeVO;
    }

}